1   /*
2    * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  package com.sun.media.sound;
26  
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.Map;
33  
34  import javax.sound.midi.MidiChannel;
35  import javax.sound.midi.Patch;
36  
37  /**
38   * Software Synthesizer MIDI channel class.
39   *
40   * @author Karl Helgason
41   */
42  public class SoftChannel implements MidiChannel, ModelDirectedPlayer {
43  
44      private static boolean[] dontResetControls = new boolean[128];
45      static {
46          for (int i = 0; i < dontResetControls.length; i++)
47              dontResetControls[i] = false;
48  
49          dontResetControls[0] = true;   // Bank Select (MSB)
50          dontResetControls[32] = true;  // Bank Select (LSB)
51          dontResetControls[7] = true;   // Channel Volume (MSB)
52          dontResetControls[8] = true;   // Balance (MSB)
53          dontResetControls[10] = true;  // Pan (MSB)
54          dontResetControls[11] = true;  // Expression (MSB)
55          dontResetControls[91] = true;  // Effects 1 Depth (default: Reverb Send)
56          dontResetControls[92] = true;  // Effects 2 Depth (default: Tremolo Depth)
57          dontResetControls[93] = true;  // Effects 3 Depth (default: Chorus Send)
58          dontResetControls[94] = true;  // Effects 4 Depth (default: Celeste [Detune] Depth)
59          dontResetControls[95] = true;  // Effects 5 Depth (default: Phaser Depth)
60          dontResetControls[70] = true;  // Sound Controller 1 (default: Sound Variation)
61          dontResetControls[71] = true;  // Sound Controller 2 (default: Timbre / Harmonic Quality)
62          dontResetControls[72] = true;  // Sound Controller 3 (default: Release Time)
63          dontResetControls[73] = true;  // Sound Controller 4 (default: Attack Time)
64          dontResetControls[74] = true;  // Sound Controller 5 (default: Brightness)
65          dontResetControls[75] = true;  // Sound Controller 6 (GM2 default: Decay Time)
66          dontResetControls[76] = true;  // Sound Controller 7 (GM2 default: Vibrato Rate)
67          dontResetControls[77] = true;  // Sound Controller 8 (GM2 default: Vibrato Depth)
68          dontResetControls[78] = true;  // Sound Controller 9 (GM2 default: Vibrato Delay)
69          dontResetControls[79] = true;  // Sound Controller 10 (GM2 default: Undefined)
70          dontResetControls[120] = true; // All Sound Off
71          dontResetControls[121] = true; // Reset All Controllers
72          dontResetControls[122] = true; // Local Control On/Off
73          dontResetControls[123] = true; // All Notes Off
74          dontResetControls[124] = true; // Omni Mode Off
75          dontResetControls[125] = true; // Omni Mode On
76          dontResetControls[126] = true; // Poly Mode Off
77          dontResetControls[127] = true; // Poly Mode On
78  
79          dontResetControls[6] = true;   // Data Entry (MSB)
80          dontResetControls[38] = true;  // Data Entry (LSB)
81          dontResetControls[96] = true;  // Data Increment
82          dontResetControls[97] = true;  // Data Decrement
83          dontResetControls[98] = true;  // Non-Registered Parameter Number (LSB)
84          dontResetControls[99] = true;  // Non-Registered Parameter Number(MSB)
85          dontResetControls[100] = true; // RPN = Null
86          dontResetControls[101] = true; // RPN = Null
87  
88      }
89  
90      private static final int RPN_NULL_VALUE = (127 << 7) + 127;
91      private int rpn_control = RPN_NULL_VALUE;
92      private int nrpn_control = RPN_NULL_VALUE;
93      protected double portamento_time = 1; // keyschanges per control buffer time
94      protected int[] portamento_lastnote = new int[128];
95      protected int portamento_lastnote_ix = 0;
96      private boolean portamento = false;
97      private boolean mono = false;
98      private boolean mute = false;
99      private boolean solo = false;
100     private boolean solomute = false;
101     private Object control_mutex;
102     private int channel;
103     private SoftVoice[] voices;
104     private int bank;
105     private int program;
106     private SoftSynthesizer synthesizer;
107     private SoftMainMixer mainmixer;
108     private int[] polypressure = new int[128];
109     private int channelpressure = 0;
110     private int[] controller = new int[128];
111     private int pitchbend;
112     private double[] co_midi_pitch = new double[1];
113     private double[] co_midi_channel_pressure = new double[1];
114     protected SoftTuning tuning = new SoftTuning();
115     protected int tuning_bank = 0;
116     protected int tuning_program = 0;
117     protected SoftInstrument current_instrument = null;
118     protected ModelChannelMixer current_mixer = null;
119     protected ModelDirector current_director = null;
120 
121     // Controller Destination Settings
122     protected int cds_control_number = -1;
123     protected ModelConnectionBlock[] cds_control_connections = null;
124     protected ModelConnectionBlock[] cds_channelpressure_connections = null;
125     protected ModelConnectionBlock[] cds_polypressure_connections = null;
126     protected boolean sustain = false;
127     protected boolean[][] keybasedcontroller_active = null;
128     protected double[][] keybasedcontroller_value = null;
129 
130     private class MidiControlObject implements SoftControl {
131         double[] pitch = co_midi_pitch;
132         double[] channel_pressure = co_midi_channel_pressure;
133         double[] poly_pressure = new double[1];
134 
135         public double[] get(int instance, String name) {
136             if (name == null)
137                 return null;
138             if (name.equals("pitch"))
139                 return pitch;
140             if (name.equals("channel_pressure"))
141                 return channel_pressure;
142             if (name.equals("poly_pressure"))
143                 return poly_pressure;
144             return null;
145         }
146     }
147 
148     private SoftControl[] co_midi = new SoftControl[128];
149     {
150         for (int i = 0; i < co_midi.length; i++) {
151             co_midi[i] = new MidiControlObject();
152         }
153     }
154 
155     private double[][] co_midi_cc_cc = new double[128][1];
156     private SoftControl co_midi_cc = new SoftControl() {
157         double[][] cc = co_midi_cc_cc;
158         public double[] get(int instance, String name) {
159             if (name == null)
160                 return null;
161             return cc[Integer.parseInt(name)];
162         }
163     };
164     Map<Integer, int[]> co_midi_rpn_rpn_i = new HashMap<Integer, int[]>();
165     Map<Integer, double[]> co_midi_rpn_rpn = new HashMap<Integer, double[]>();
166     private SoftControl co_midi_rpn = new SoftControl() {
167         Map<Integer, double[]> rpn = co_midi_rpn_rpn;
168         public double[] get(int instance, String name) {
169             if (name == null)
170                 return null;
171             int iname = Integer.parseInt(name);
172             double[] v = rpn.get(iname);
173             if (v == null) {
174                 v = new double[1];
175                 rpn.put(iname, v);
176             }
177             return v;
178         }
179     };
180     Map<Integer, int[]> co_midi_nrpn_nrpn_i = new HashMap<Integer, int[]>();
181     Map<Integer, double[]> co_midi_nrpn_nrpn = new HashMap<Integer, double[]>();
182     private SoftControl co_midi_nrpn = new SoftControl() {
183         Map<Integer, double[]> nrpn = co_midi_nrpn_nrpn;
184         public double[] get(int instance, String name) {
185             if (name == null)
186                 return null;
187             int iname = Integer.parseInt(name);
188             double[] v = nrpn.get(iname);
189             if (v == null) {
190                 v = new double[1];
191                 nrpn.put(iname, v);
192             }
193             return v;
194         }
195     };
196 
197     private static int restrict7Bit(int value)
198     {
199         if(value < 0) return 0;
200         if(value > 127) return 127;
201         return value;
202     }
203 
204     private static int restrict14Bit(int value)
205     {
206         if(value < 0) return 0;
207         if(value > 16256) return 16256;
208         return value;
209     }
210 
211     public SoftChannel(SoftSynthesizer synth, int channel) {
212         this.channel = channel;
213         this.voices = synth.getVoices();
214         this.synthesizer = synth;
215         this.mainmixer = synth.getMainMixer();
216         control_mutex = synth.control_mutex;
217         resetAllControllers(true);
218     }
219 
220     private int findFreeVoice(int x) {
221         if(x == -1)
222         {
223             // x = -1 means that there where no available voice
224             // last time we called findFreeVoice
225             // and it hasn't changed because no audio has been
226             // rendered in the meantime.
227             // Therefore we have to return -1.
228             return -1;
229         }
230         for (int i = x; i < voices.length; i++)
231             if (!voices[i].active)
232                 return i;
233 
234         // No free voice was found, we must steal one
235 
236         int vmode = synthesizer.getVoiceAllocationMode();
237         if (vmode == 1) {
238             // DLS Static Voice Allocation
239 
240             //  * priority ( 10, 1-9, 11-16)
241             // Search for channel to steal from
242             int steal_channel = channel;
243             for (int j = 0; j < voices.length; j++) {
244                 if (voices[j].stealer_channel == null) {
245                     if (steal_channel == 9) {
246                         steal_channel = voices[j].channel;
247                     } else {
248                         if (voices[j].channel != 9) {
249                             if (voices[j].channel > steal_channel)
250                                 steal_channel = voices[j].channel;
251                         }
252                     }
253                 }
254             }
255 
256             int voiceNo = -1;
257 
258             SoftVoice v = null;
259             // Search for oldest voice in off state on steal_channel
260             for (int j = 0; j < voices.length; j++) {
261                 if (voices[j].channel == steal_channel) {
262                     if (voices[j].stealer_channel == null && !voices[j].on) {
263                         if (v == null) {
264                             v = voices[j];
265                             voiceNo = j;
266                         }
267                         if (voices[j].voiceID < v.voiceID) {
268                             v = voices[j];
269                             voiceNo = j;
270                         }
271                     }
272                 }
273             }
274             // Search for oldest voice in on state on steal_channel
275             if (voiceNo == -1) {
276                 for (int j = 0; j < voices.length; j++) {
277                     if (voices[j].channel == steal_channel) {
278                         if (voices[j].stealer_channel == null) {
279                             if (v == null) {
280                                 v = voices[j];
281                                 voiceNo = j;
282                             }
283                             if (voices[j].voiceID < v.voiceID) {
284                                 v = voices[j];
285                                 voiceNo = j;
286                             }
287                         }
288                     }
289                 }
290             }
291 
292             return voiceNo;
293 
294         } else {
295             // Default Voice Allocation
296             //  * Find voice that is on
297             //    and Find voice which has lowest voiceID ( oldest voice)
298             //  * Or find voice that is off
299             //    and Find voice which has lowest voiceID ( oldest voice)
300 
301             int voiceNo = -1;
302 
303             SoftVoice v = null;
304             // Search for oldest voice in off state
305             for (int j = 0; j < voices.length; j++) {
306                 if (voices[j].stealer_channel == null && !voices[j].on) {
307                     if (v == null) {
308                         v = voices[j];
309                         voiceNo = j;
310                     }
311                     if (voices[j].voiceID < v.voiceID) {
312                         v = voices[j];
313                         voiceNo = j;
314                     }
315                 }
316             }
317             // Search for oldest voice in on state
318             if (voiceNo == -1) {
319 
320                 for (int j = 0; j < voices.length; j++) {
321                     if (voices[j].stealer_channel == null) {
322                         if (v == null) {
323                             v = voices[j];
324                             voiceNo = j;
325                         }
326                         if (voices[j].voiceID < v.voiceID) {
327                             v = voices[j];
328                             voiceNo = j;
329                         }
330                     }
331                 }
332             }
333 
334             return voiceNo;
335         }
336 
337     }
338 
339     protected void initVoice(SoftVoice voice, SoftPerformer p, int voiceID,
340             int noteNumber, int velocity, int delay, ModelConnectionBlock[] connectionBlocks,
341             ModelChannelMixer channelmixer, boolean releaseTriggered) {
342         if (voice.active) {
343             // Voice is active , we must steal the voice
344             voice.stealer_channel = this;
345             voice.stealer_performer = p;
346             voice.stealer_voiceID = voiceID;
347             voice.stealer_noteNumber = noteNumber;
348             voice.stealer_velocity = velocity;
349             voice.stealer_extendedConnectionBlocks = connectionBlocks;
350             voice.stealer_channelmixer = channelmixer;
351             voice.stealer_releaseTriggered = releaseTriggered;
352             for (int i = 0; i < voices.length; i++)
353                 if (voices[i].active && voices[i].voiceID == voice.voiceID)
354                     voices[i].soundOff();
355             return;
356         }
357 
358         voice.extendedConnectionBlocks = connectionBlocks;
359         voice.channelmixer = channelmixer;
360         voice.releaseTriggered = releaseTriggered;
361         voice.voiceID = voiceID;
362         voice.tuning = tuning;
363         voice.exclusiveClass = p.exclusiveClass;
364         voice.softchannel = this;
365         voice.channel = channel;
366         voice.bank = bank;
367         voice.program = program;
368         voice.instrument = current_instrument;
369         voice.performer = p;
370         voice.objects.clear();
371         voice.objects.put("midi", co_midi[noteNumber]);
372         voice.objects.put("midi_cc", co_midi_cc);
373         voice.objects.put("midi_rpn", co_midi_rpn);
374         voice.objects.put("midi_nrpn", co_midi_nrpn);
375         voice.noteOn(noteNumber, velocity, delay);
376         voice.setMute(mute);
377         voice.setSoloMute(solomute);
378         if (releaseTriggered)
379             return;
380         if (controller[84] != 0) {
381             voice.co_noteon_keynumber[0]
382                     = (tuning.getTuning(controller[84]) / 100.0)
383                     * (1f / 128f);
384             voice.portamento = true;
385             controlChange(84, 0);
386         } else if (portamento) {
387             if (mono) {
388                 if (portamento_lastnote[0] != -1) {
389                     voice.co_noteon_keynumber[0]
390                             = (tuning.getTuning(portamento_lastnote[0]) / 100.0)
391                             * (1f / 128f);
392                     voice.portamento = true;
393                     controlChange(84, 0);
394                 }
395                 portamento_lastnote[0] = noteNumber;
396             } else {
397                 if (portamento_lastnote_ix != 0) {
398                     portamento_lastnote_ix--;
399                     voice.co_noteon_keynumber[0]
400                             = (tuning.getTuning(
401                                     portamento_lastnote[portamento_lastnote_ix])
402                                 / 100.0)
403                             * (1f / 128f);
404                     voice.portamento = true;
405                 }
406             }
407         }
408     }
409 
410     public void noteOn(int noteNumber, int velocity) {
411         noteOn(noteNumber, velocity, 0);
412     }
413 
414     /* A special noteOn with delay parameter, which is used to
415      * start note within control buffers.
416      */
417     protected void noteOn(int noteNumber, int velocity, int delay) {
418         noteNumber = restrict7Bit(noteNumber);
419         velocity = restrict7Bit(velocity);
420         noteOn_internal(noteNumber, velocity, delay);
421         if (current_mixer != null)
422             current_mixer.noteOn(noteNumber, velocity);
423     }
424 
425     private void noteOn_internal(int noteNumber, int velocity, int delay) {
426 
427         if (velocity == 0) {
428             noteOff_internal(noteNumber, 64);
429             return;
430         }
431 
432         synchronized (control_mutex) {
433             if (sustain) {
434                 sustain = false;
435                 for (int i = 0; i < voices.length; i++) {
436                     if ((voices[i].sustain || voices[i].on)
437                             && voices[i].channel == channel && voices[i].active
438                             && voices[i].note == noteNumber) {
439                         voices[i].sustain = false;
440                         voices[i].on = true;
441                         voices[i].noteOff(0);
442                     }
443                 }
444                 sustain = true;
445             }
446 
447             mainmixer.activity();
448 
449             if (mono) {
450                 if (portamento) {
451                     boolean n_found = false;
452                     for (int i = 0; i < voices.length; i++) {
453                         if (voices[i].on && voices[i].channel == channel
454                                 && voices[i].active
455                                 && voices[i].releaseTriggered == false) {
456                             voices[i].portamento = true;
457                             voices[i].setNote(noteNumber);
458                             n_found = true;
459                         }
460                     }
461                     if (n_found) {
462                         portamento_lastnote[0] = noteNumber;
463                         return;
464                     }
465                 }
466 
467                 if (controller[84] != 0) {
468                     boolean n_found = false;
469                     for (int i = 0; i < voices.length; i++) {
470                         if (voices[i].on && voices[i].channel == channel
471                                 && voices[i].active
472                                 && voices[i].note == controller[84]
473                                 && voices[i].releaseTriggered == false) {
474                             voices[i].portamento = true;
475                             voices[i].setNote(noteNumber);
476                             n_found = true;
477                         }
478                     }
479                     controlChange(84, 0);
480                     if (n_found)
481                         return;
482                 }
483             }
484 
485             if (mono)
486                 allNotesOff();
487 
488             if (current_instrument == null) {
489                 current_instrument
490                         = synthesizer.findInstrument(program, bank, channel);
491                 if (current_instrument == null)
492                     return;
493                 if (current_mixer != null)
494                     mainmixer.stopMixer(current_mixer);
495                 current_mixer = current_instrument.getSourceInstrument()
496                         .getChannelMixer(this, synthesizer.getFormat());
497                 if (current_mixer != null)
498                     mainmixer.registerMixer(current_mixer);
499                 current_director = current_instrument.getDirector(this, this);
500                 applyInstrumentCustomization();
501             }
502             prevVoiceID = synthesizer.voiceIDCounter++;
503             firstVoice = true;
504             voiceNo = 0;
505 
506             int tunedKey = (int)(Math.round(tuning.getTuning(noteNumber)/100.0));
507             play_noteNumber = noteNumber;
508             play_velocity = velocity;
509             play_delay = delay;
510             play_releasetriggered = false;
511             lastVelocity[noteNumber] = velocity;
512             current_director.noteOn(tunedKey, velocity);
513 
514             /*
515             SoftPerformer[] performers = current_instrument.getPerformers();
516             for (int i = 0; i < performers.length; i++) {
517                 SoftPerformer p = performers[i];
518                 if (p.keyFrom <= tunedKey && p.keyTo >= tunedKey) {
519                     if (p.velFrom <= velocity && p.velTo >= velocity) {
520                         if (firstVoice) {
521                             firstVoice = false;
522                             if (p.exclusiveClass != 0) {
523                                 int x = p.exclusiveClass;
524                                 for (int j = 0; j < voices.length; j++) {
525                                     if (voices[j].active
526                                             && voices[j].channel == channel
527                                             && voices[j].exclusiveClass == x) {
528                                         if (!(p.selfNonExclusive
529                                                 && voices[j].note == noteNumber))
530                                             voices[j].shutdown();
531                                     }
532                                 }
533                             }
534                         }
535                         voiceNo = findFreeVoice(voiceNo);
536                         if (voiceNo == -1)
537                             return;
538                         initVoice(voices[voiceNo], p, prevVoiceID, noteNumber,
539                                 velocity);
540                     }
541                 }
542             }
543             */
544         }
545     }
546 
547     public void noteOff(int noteNumber, int velocity) {
548         noteNumber = restrict7Bit(noteNumber);
549         velocity = restrict7Bit(velocity);
550         noteOff_internal(noteNumber, velocity);
551 
552         if (current_mixer != null)
553             current_mixer.noteOff(noteNumber, velocity);
554     }
555 
556     private void noteOff_internal(int noteNumber, int velocity) {
557         synchronized (control_mutex) {
558 
559             if (!mono) {
560                 if (portamento) {
561                     if (portamento_lastnote_ix != 127) {
562                         portamento_lastnote[portamento_lastnote_ix] = noteNumber;
563                         portamento_lastnote_ix++;
564                     }
565                 }
566             }
567 
568             mainmixer.activity();
569             for (int i = 0; i < voices.length; i++) {
570                 if (voices[i].on && voices[i].channel == channel
571                         && voices[i].note == noteNumber
572                         && voices[i].releaseTriggered == false) {
573                     voices[i].noteOff(velocity);
574                 }
575                 // We must also check stolen voices
576                 if (voices[i].stealer_channel == this && voices[i].stealer_noteNumber == noteNumber) {
577                     SoftVoice v = voices[i];
578                     v.stealer_releaseTriggered = false;
579                     v.stealer_channel = null;
580                     v.stealer_performer = null;
581                     v.stealer_voiceID = -1;
582                     v.stealer_noteNumber = 0;
583                     v.stealer_velocity = 0;
584                     v.stealer_extendedConnectionBlocks = null;
585                     v.stealer_channelmixer = null;
586                 }
587             }
588 
589             // Try play back note-off triggered voices,
590 
591             if (current_instrument == null) {
592                 current_instrument
593                         = synthesizer.findInstrument(program, bank, channel);
594                 if (current_instrument == null)
595                     return;
596                 if (current_mixer != null)
597                     mainmixer.stopMixer(current_mixer);
598                 current_mixer = current_instrument.getSourceInstrument()
599                         .getChannelMixer(this, synthesizer.getFormat());
600                 if (current_mixer != null)
601                     mainmixer.registerMixer(current_mixer);
602                 current_director = current_instrument.getDirector(this, this);
603                 applyInstrumentCustomization();
604 
605             }
606             prevVoiceID = synthesizer.voiceIDCounter++;
607             firstVoice = true;
608             voiceNo = 0;
609 
610             int tunedKey = (int)(Math.round(tuning.getTuning(noteNumber)/100.0));
611             play_noteNumber = noteNumber;
612             play_velocity = lastVelocity[noteNumber];
613             play_releasetriggered = true;
614             play_delay = 0;
615             current_director.noteOff(tunedKey, velocity);
616 
617         }
618     }
619     private int[] lastVelocity = new int[128];
620     private int prevVoiceID;
621     private boolean firstVoice = true;
622     private int voiceNo = 0;
623     private int play_noteNumber = 0;
624     private int play_velocity = 0;
625     private int play_delay = 0;
626     private boolean play_releasetriggered = false;
627 
628     public void play(int performerIndex, ModelConnectionBlock[] connectionBlocks) {
629 
630         int noteNumber = play_noteNumber;
631         int velocity = play_velocity;
632         int delay = play_delay;
633         boolean releasetriggered = play_releasetriggered;
634 
635         SoftPerformer p = current_instrument.getPerformer(performerIndex);
636 
637         if (firstVoice) {
638             firstVoice = false;
639             if (p.exclusiveClass != 0) {
640                 int x = p.exclusiveClass;
641                 for (int j = 0; j < voices.length; j++) {
642                     if (voices[j].active && voices[j].channel == channel
643                             && voices[j].exclusiveClass == x) {
644                         if (!(p.selfNonExclusive && voices[j].note == noteNumber))
645                             voices[j].shutdown();
646                     }
647                 }
648             }
649         }
650 
651         voiceNo = findFreeVoice(voiceNo);
652 
653         if (voiceNo == -1)
654             return;
655 
656         initVoice(voices[voiceNo], p, prevVoiceID, noteNumber, velocity, delay,
657                 connectionBlocks, current_mixer, releasetriggered);
658     }
659 
660     public void noteOff(int noteNumber) {
661         if(noteNumber < 0 || noteNumber > 127) return;
662         noteOff_internal(noteNumber, 64);
663     }
664 
665     public void setPolyPressure(int noteNumber, int pressure) {
666         noteNumber = restrict7Bit(noteNumber);
667         pressure = restrict7Bit(pressure);
668 
669         if (current_mixer != null)
670             current_mixer.setPolyPressure(noteNumber, pressure);
671 
672         synchronized (control_mutex) {
673             mainmixer.activity();
674             co_midi[noteNumber].get(0, "poly_pressure")[0] = pressure*(1.0/128.0);
675             polypressure[noteNumber] = pressure;
676             for (int i = 0; i < voices.length; i++) {
677                 if (voices[i].active && voices[i].note == noteNumber)
678                     voices[i].setPolyPressure(pressure);
679             }
680         }
681     }
682 
683     public int getPolyPressure(int noteNumber) {
684         synchronized (control_mutex) {
685             return polypressure[noteNumber];
686         }
687     }
688 
689     public void setChannelPressure(int pressure) {
690         pressure = restrict7Bit(pressure);
691         if (current_mixer != null)
692             current_mixer.setChannelPressure(pressure);
693         synchronized (control_mutex) {
694             mainmixer.activity();
695             co_midi_channel_pressure[0] = pressure * (1.0 / 128.0);
696             channelpressure = pressure;
697             for (int i = 0; i < voices.length; i++) {
698                 if (voices[i].active)
699                     voices[i].setChannelPressure(pressure);
700             }
701         }
702     }
703 
704     public int getChannelPressure() {
705         synchronized (control_mutex) {
706             return channelpressure;
707         }
708     }
709 
710     protected void applyInstrumentCustomization() {
711         if (cds_control_connections == null
712                 && cds_channelpressure_connections == null
713                 && cds_polypressure_connections == null) {
714             return;
715         }
716 
717         ModelInstrument src_instrument = current_instrument.getSourceInstrument();
718         ModelPerformer[] performers = src_instrument.getPerformers();
719         ModelPerformer[] new_performers = new ModelPerformer[performers.length];
720         for (int i = 0; i < new_performers.length; i++) {
721             ModelPerformer performer = performers[i];
722             ModelPerformer new_performer = new ModelPerformer();
723             new_performer.setName(performer.getName());
724             new_performer.setExclusiveClass(performer.getExclusiveClass());
725             new_performer.setKeyFrom(performer.getKeyFrom());
726             new_performer.setKeyTo(performer.getKeyTo());
727             new_performer.setVelFrom(performer.getVelFrom());
728             new_performer.setVelTo(performer.getVelTo());
729             new_performer.getOscillators().addAll(performer.getOscillators());
730             new_performer.getConnectionBlocks().addAll(
731                     performer.getConnectionBlocks());
732             new_performers[i] = new_performer;
733 
734             List<ModelConnectionBlock> connblocks =
735                     new_performer.getConnectionBlocks();
736 
737             if (cds_control_connections != null) {
738                 String cc = Integer.toString(cds_control_number);
739                 Iterator<ModelConnectionBlock> iter = connblocks.iterator();
740                 while (iter.hasNext()) {
741                     ModelConnectionBlock conn = iter.next();
742                     ModelSource[] sources = conn.getSources();
743                     boolean removeok = false;
744                     if (sources != null) {
745                         for (int j = 0; j < sources.length; j++) {
746                             ModelSource src = sources[j];
747                             if ("midi_cc".equals(src.getIdentifier().getObject())
748                                     && cc.equals(src.getIdentifier().getVariable())) {
749                                 removeok = true;
750                             }
751                         }
752                     }
753                     if (removeok)
754                         iter.remove();
755                 }
756                 for (int j = 0; j < cds_control_connections.length; j++)
757                     connblocks.add(cds_control_connections[j]);
758             }
759 
760             if (cds_polypressure_connections != null) {
761                 Iterator<ModelConnectionBlock> iter = connblocks.iterator();
762                 while (iter.hasNext()) {
763                     ModelConnectionBlock conn = iter.next();
764                     ModelSource[] sources = conn.getSources();
765                     boolean removeok = false;
766                     if (sources != null) {
767                         for (int j = 0; j < sources.length; j++) {
768                             ModelSource src = sources[j];
769                             if ("midi".equals(src.getIdentifier().getObject())
770                                     && "poly_pressure".equals(
771                                         src.getIdentifier().getVariable())) {
772                                 removeok = true;
773                             }
774                         }
775                     }
776                     if (removeok)
777                         iter.remove();
778                 }
779                 for (int j = 0; j < cds_polypressure_connections.length; j++)
780                     connblocks.add(cds_polypressure_connections[j]);
781             }
782 
783 
784             if (cds_channelpressure_connections != null) {
785                 Iterator<ModelConnectionBlock> iter = connblocks.iterator();
786                 while (iter.hasNext()) {
787                     ModelConnectionBlock conn = iter.next();
788                     ModelSource[] sources = conn.getSources();
789                     boolean removeok = false;
790                     if (sources != null) {
791                         for (int j = 0; j < sources.length; j++) {
792                             ModelIdentifier srcid = sources[j].getIdentifier();
793                             if ("midi".equals(srcid.getObject()) &&
794                                     "channel_pressure".equals(srcid.getVariable())) {
795                                 removeok = true;
796                             }
797                         }
798                     }
799                     if (removeok)
800                         iter.remove();
801                 }
802                 for (int j = 0; j < cds_channelpressure_connections.length; j++)
803                     connblocks.add(cds_channelpressure_connections[j]);
804             }
805 
806         }
807 
808         current_instrument = new SoftInstrument(src_instrument, new_performers);
809 
810     }
811 
812     private ModelConnectionBlock[] createModelConnections(ModelIdentifier sid,
813             int[] destination, int[] range) {
814 
815         /*
816         controlled parameter (pp)|range (rr)| Description             |Default
817         -------------------------|----------|-------------------------|-------
818         00 Pitch Control         | 28H..58H | -24..+24 semitones      | 40H
819         01 Filter Cutoff Control | 00H..7FH | -9600..+9450 cents      | 40H
820         02 Amplitude Control     | 00H..7FH | 0..(127/64)*100 percent | 40H
821         03 LFO Pitch Depth       | 00H..7FH | 0..600 cents            |  0
822         04 LFO Filter Depth      | 00H..7FH | 0..2400 cents           |  0
823         05 LFO Amplitude Depth   | 00H..7FH | 0..100 percent          |  0
824         */
825 
826         List<ModelConnectionBlock> conns = new ArrayList<ModelConnectionBlock>();
827 
828         for (int i = 0; i < destination.length; i++) {
829             int d = destination[i];
830             int r = range[i];
831             if (d == 0) {
832                 double scale = (r - 64) * 100;
833                 ModelConnectionBlock conn = new ModelConnectionBlock(
834                         new ModelSource(sid,
835                             ModelStandardTransform.DIRECTION_MIN2MAX,
836                             ModelStandardTransform.POLARITY_UNIPOLAR,
837                             ModelStandardTransform.TRANSFORM_LINEAR),
838                         scale,
839                         new ModelDestination(
840                             new ModelIdentifier("osc", "pitch")));
841                 conns.add(conn);
842 
843             }
844             if (d == 1) {
845                 double scale = (r / 64.0 - 1.0) * 9600.0;
846                 ModelConnectionBlock conn;
847                 if (scale > 0) {
848                     conn = new ModelConnectionBlock(
849                             new ModelSource(sid,
850                                 ModelStandardTransform.DIRECTION_MAX2MIN,
851                                 ModelStandardTransform.POLARITY_UNIPOLAR,
852                                 ModelStandardTransform.TRANSFORM_LINEAR),
853                             -scale,
854                             new ModelDestination(
855                                 ModelDestination.DESTINATION_FILTER_FREQ));
856                 } else {
857                     conn = new ModelConnectionBlock(
858                             new ModelSource(sid,
859                                 ModelStandardTransform.DIRECTION_MIN2MAX,
860                                 ModelStandardTransform.POLARITY_UNIPOLAR,
861                                 ModelStandardTransform.TRANSFORM_LINEAR),
862                             scale,
863                             new ModelDestination(
864                                 ModelDestination.DESTINATION_FILTER_FREQ));
865                 }
866                 conns.add(conn);
867             }
868             if (d == 2) {
869                 final double scale = (r / 64.0);
870                 ModelTransform mt = new ModelTransform() {
871                     double s = scale;
872                     public double transform(double value) {
873                         if (s < 1)
874                             value = s + (value * (1.0 - s));
875                         else if (s > 1)
876                             value = 1 + (value * (s - 1.0));
877                         else
878                             return 0;
879                         return -((5.0 / 12.0) / Math.log(10)) * Math.log(value);
880                     }
881                 };
882 
883                 ModelConnectionBlock conn = new ModelConnectionBlock(
884                         new ModelSource(sid, mt), -960,
885                         new ModelDestination(ModelDestination.DESTINATION_GAIN));
886                 conns.add(conn);
887 
888             }
889             if (d == 3) {
890                 double scale = (r / 64.0 - 1.0) * 9600.0;
891                 ModelConnectionBlock conn = new ModelConnectionBlock(
892                         new ModelSource(ModelSource.SOURCE_LFO1,
893                             ModelStandardTransform.DIRECTION_MIN2MAX,
894                             ModelStandardTransform.POLARITY_BIPOLAR,
895                             ModelStandardTransform.TRANSFORM_LINEAR),
896                         new ModelSource(sid,
897                             ModelStandardTransform.DIRECTION_MIN2MAX,
898                             ModelStandardTransform.POLARITY_UNIPOLAR,
899                             ModelStandardTransform.TRANSFORM_LINEAR),
900                         scale,
901                         new ModelDestination(
902                             ModelDestination.DESTINATION_PITCH));
903                 conns.add(conn);
904             }
905             if (d == 4) {
906                 double scale = (r / 128.0) * 2400.0;
907                 ModelConnectionBlock conn = new ModelConnectionBlock(
908                         new ModelSource(ModelSource.SOURCE_LFO1,
909                             ModelStandardTransform.DIRECTION_MIN2MAX,
910                             ModelStandardTransform.POLARITY_BIPOLAR,
911                             ModelStandardTransform.TRANSFORM_LINEAR),
912                         new ModelSource(sid,
913                             ModelStandardTransform.DIRECTION_MIN2MAX,
914                             ModelStandardTransform.POLARITY_UNIPOLAR,
915                             ModelStandardTransform.TRANSFORM_LINEAR),
916                         scale,
917                         new ModelDestination(
918                             ModelDestination.DESTINATION_FILTER_FREQ));
919                 conns.add(conn);
920             }
921             if (d == 5) {
922                 final double scale = (r / 127.0);
923 
924                 ModelTransform mt = new ModelTransform() {
925                     double s = scale;
926                     public double transform(double value) {
927                         return -((5.0 / 12.0) / Math.log(10))
928                                 * Math.log(1 - value * s);
929                     }
930                 };
931 
932                 ModelConnectionBlock conn = new ModelConnectionBlock(
933                         new ModelSource(ModelSource.SOURCE_LFO1,
934                             ModelStandardTransform.DIRECTION_MIN2MAX,
935                             ModelStandardTransform.POLARITY_UNIPOLAR,
936                             ModelStandardTransform.TRANSFORM_LINEAR),
937                         new ModelSource(sid, mt),
938                         -960,
939                         new ModelDestination(
940                             ModelDestination.DESTINATION_GAIN));
941                 conns.add(conn);
942             }
943         }
944 
945         return conns.toArray(new ModelConnectionBlock[conns.size()]);
946     }
947 
948     public void mapPolyPressureToDestination(int[] destination, int[] range) {
949         current_instrument = null;
950         if (destination.length == 0) {
951             cds_polypressure_connections = null;
952             return;
953         }
954         cds_polypressure_connections
955                 = createModelConnections(
956                     new ModelIdentifier("midi", "poly_pressure"),
957                     destination, range);
958     }
959 
960     public void mapChannelPressureToDestination(int[] destination, int[] range) {
961         current_instrument = null;
962         if (destination.length == 0) {
963             cds_channelpressure_connections = null;
964             return;
965         }
966         cds_channelpressure_connections
967                 = createModelConnections(
968                     new ModelIdentifier("midi", "channel_pressure"),
969                     destination, range);
970     }
971 
972     public void mapControlToDestination(int control, int[] destination, int[] range) {
973 
974         if (!((control >= 0x01 && control <= 0x1F)
975                 || (control >= 0x40 && control <= 0x5F))) {
976             cds_control_connections = null;
977             return;
978         }
979 
980         current_instrument = null;
981         cds_control_number = control;
982         if (destination.length == 0) {
983             cds_control_connections = null;
984             return;
985         }
986         cds_control_connections
987                 = createModelConnections(
988                     new ModelIdentifier("midi_cc", Integer.toString(control)),
989                     destination, range);
990     }
991 
992     public void controlChangePerNote(int noteNumber, int controller, int value) {
993 
994 /*
995  CC# | nn   | Name                    | vv             | default    | description
996 -----|------|-------------------------|----------------|------------|-------------------------------
997 7    |07H   |Note Volume              |00H-40H-7FH     |40H         |0-100-(127/64)*100(%)(Relative)
998 10   |0AH   |*Pan                     |00H-7FH absolute|Preset Value|Left-Center-Right (absolute)
999 33-63|21-3FH|LSB for                  |01H-1FH         |            |
1000 71   |47H   |Timbre/Harmonic Intensity|00H-40H-7FH     |40H (???)   |
1001 72   |48H   |Release Time             |00H-40H-7FH     |40H (???)   |
1002 73   |49H   |Attack Time              |00H-40H-7FH     |40H (???)   |
1003 74   |4AH   |Brightness               |00H-40H-7FH     |40H (???)   |
1004 75   |4BH   |Decay Time               |00H-40H-7FH     |40H (???)   |
1005 76   |4CH   |Vibrato Rate             |00H-40H-7FH     |40H (???)   |
1006 77   |4DH   |Vibrato Depth            |00H-40H-7FH     |40H (???)   |
1007 78   |4EH   |Vibrato Delay            |00H-40H-7FH     |40H (???)   |
1008 91   |5BH   |*Reverb Send             |00H-7FH absolute|Preset Value|Left-Center-Right (absolute)
1009 93   |5DH   |*Chorus Send             |00H-7FH absolute|Preset Value|Left-Center-Right (absolute)
1010 120  |78H   |**Fine Tuning            |00H-40H-7FH     |40H (???)   |
1011 121  |79H   |**Coarse Tuning          |00H-40H-7FH     |40H (???)   |
1012 */
1013 
1014         if (keybasedcontroller_active == null) {
1015             keybasedcontroller_active = new boolean[128][];
1016             keybasedcontroller_value = new double[128][];
1017         }
1018         if (keybasedcontroller_active[noteNumber] == null) {
1019             keybasedcontroller_active[noteNumber] = new boolean[128];
1020             Arrays.fill(keybasedcontroller_active[noteNumber], false);
1021             keybasedcontroller_value[noteNumber] = new double[128];
1022             Arrays.fill(keybasedcontroller_value[noteNumber], 0);
1023         }
1024 
1025         if (value == -1) {
1026             keybasedcontroller_active[noteNumber][controller] = false;
1027         } else {
1028             keybasedcontroller_active[noteNumber][controller] = true;
1029             keybasedcontroller_value[noteNumber][controller] = value / 128.0;
1030         }
1031 
1032         if (controller < 120) {
1033             for (int i = 0; i < voices.length; i++)
1034                 if (voices[i].active)
1035                     voices[i].controlChange(controller, -1);
1036         } else if (controller == 120) {
1037             for (int i = 0; i < voices.length; i++)
1038                 if (voices[i].active)
1039                     voices[i].rpnChange(1, -1);
1040         } else if (controller == 121) {
1041             for (int i = 0; i < voices.length; i++)
1042                 if (voices[i].active)
1043                     voices[i].rpnChange(2, -1);
1044         }
1045 
1046     }
1047 
1048     public int getControlPerNote(int noteNumber, int controller) {
1049         if (keybasedcontroller_active == null)
1050             return -1;
1051         if (keybasedcontroller_active[noteNumber] == null)
1052             return -1;
1053         if (!keybasedcontroller_active[noteNumber][controller])
1054             return -1;
1055         return (int)(keybasedcontroller_value[noteNumber][controller] * 128);
1056     }
1057 
1058     public void controlChange(int controller, int value) {
1059         controller = restrict7Bit(controller);
1060         value = restrict7Bit(value);
1061         if (current_mixer != null)
1062             current_mixer.controlChange(controller, value);
1063 
1064         synchronized (control_mutex) {
1065             switch (controller) {
1066             /*
1067             Map<String, int[]>co_midi_rpn_rpn_i = new HashMap<String, int[]>();
1068             Map<String, double[]>co_midi_rpn_rpn = new HashMap<String, double[]>();
1069             Map<String, int[]>co_midi_nrpn_nrpn_i = new HashMap<String, int[]>();
1070             Map<String, double[]>co_midi_nrpn_nrpn = new HashMap<String, double[]>();
1071              */
1072 
1073             case 5:
1074                 // This produce asin-like curve
1075                 // as described in General Midi Level 2 Specification, page 6
1076                 double x = -Math.asin((value / 128.0) * 2 - 1) / Math.PI + 0.5;
1077                 x = Math.pow(100000.0, x) / 100.0;  // x is now cent/msec
1078                 // Convert x from cent/msec to key/controlbuffertime
1079                 x = x / 100.0;                      // x is now keys/msec
1080                 x = x * 1000.0;                     // x is now keys/sec
1081                 x = x / synthesizer.getControlRate(); // x is now keys/controlbuffertime
1082                 portamento_time = x;
1083                 break;
1084             case 6:
1085             case 38:
1086             case 96:
1087             case 97:
1088                 int val = 0;
1089                 if (nrpn_control != RPN_NULL_VALUE) {
1090                     int[] val_i = co_midi_nrpn_nrpn_i.get(nrpn_control);
1091                     if (val_i != null)
1092                         val = val_i[0];
1093                 }
1094                 if (rpn_control != RPN_NULL_VALUE) {
1095                     int[] val_i = co_midi_rpn_rpn_i.get(rpn_control);
1096                     if (val_i != null)
1097                         val = val_i[0];
1098                 }
1099 
1100                 if (controller == 6)
1101                     val = (val & 127) + (value << 7);
1102                 else if (controller == 38)
1103                     val = (val & (127 << 7)) + value;
1104                 else if (controller == 96 || controller == 97) {
1105                     int step = 1;
1106                     if (rpn_control == 2 || rpn_control == 3 || rpn_control == 4)
1107                         step = 128;
1108                     if (controller == 96)
1109                         val += step;
1110                     if (controller == 97)
1111                         val -= step;
1112                 }
1113 
1114                 if (nrpn_control != RPN_NULL_VALUE)
1115                     nrpnChange(nrpn_control, val);
1116                 if (rpn_control != RPN_NULL_VALUE)
1117                     rpnChange(rpn_control, val);
1118 
1119                 break;
1120             case 64: // Hold1 (Damper) (cc#64)
1121                 boolean on = value >= 64;
1122                 if (sustain != on) {
1123                     sustain = on;
1124                     if (!on) {
1125                         for (int i = 0; i < voices.length; i++) {
1126                             if (voices[i].active && voices[i].sustain &&
1127                                     voices[i].channel == channel) {
1128                                 voices[i].sustain = false;
1129                                 if (!voices[i].on) {
1130                                     voices[i].on = true;
1131                                     voices[i].noteOff(0);
1132                                 }
1133                             }
1134                         }
1135                     } else {
1136                         for (int i = 0; i < voices.length; i++)
1137                             if (voices[i].active && voices[i].channel == channel)
1138                                 voices[i].redamp();
1139                     }
1140                 }
1141                 break;
1142             case 65:
1143                 //allNotesOff();
1144                 portamento = value >= 64;
1145                 portamento_lastnote[0] = -1;
1146                 /*
1147                 for (int i = 0; i < portamento_lastnote.length; i++)
1148                     portamento_lastnote[i] = -1;
1149                  */
1150                 portamento_lastnote_ix = 0;
1151                 break;
1152             case 66: // Sostenuto (cc#66)
1153                 on = value >= 64;
1154                 if (on) {
1155                     for (int i = 0; i < voices.length; i++) {
1156                         if (voices[i].active && voices[i].on &&
1157                                 voices[i].channel == channel) {
1158                             voices[i].sostenuto = true;
1159                         }
1160                     }
1161                 }
1162                 if (!on) {
1163                     for (int i = 0; i < voices.length; i++) {
1164                         if (voices[i].active && voices[i].sostenuto &&
1165                                 voices[i].channel == channel) {
1166                             voices[i].sostenuto = false;
1167                             if (!voices[i].on) {
1168                                 voices[i].on = true;
1169                                 voices[i].noteOff(0);
1170                             }
1171                         }
1172                     }
1173                 }
1174                 break;
1175             case 98:
1176                 nrpn_control = (nrpn_control & (127 << 7)) + value;
1177                 rpn_control = RPN_NULL_VALUE;
1178                 break;
1179             case 99:
1180                 nrpn_control = (nrpn_control & 127) + (value << 7);
1181                 rpn_control = RPN_NULL_VALUE;
1182                 break;
1183             case 100:
1184                 rpn_control = (rpn_control & (127 << 7)) + value;
1185                 nrpn_control = RPN_NULL_VALUE;
1186                 break;
1187             case 101:
1188                 rpn_control = (rpn_control & 127) + (value << 7);
1189                 nrpn_control = RPN_NULL_VALUE;
1190                 break;
1191             case 120:
1192                 allSoundOff();
1193                 break;
1194             case 121:
1195                 resetAllControllers(value == 127);
1196                 break;
1197             case 122:
1198                 localControl(value >= 64);
1199                 break;
1200             case 123:
1201                 allNotesOff();
1202                 break;
1203             case 124:
1204                 setOmni(false);
1205                 break;
1206             case 125:
1207                 setOmni(true);
1208                 break;
1209             case 126:
1210                 if (value == 1)
1211                     setMono(true);
1212                 break;
1213             case 127:
1214                 setMono(false);
1215                 break;
1216 
1217             default:
1218                 break;
1219             }
1220 
1221             co_midi_cc_cc[controller][0] = value * (1.0 / 128.0);
1222 
1223             if (controller == 0x00) {
1224                 bank = /*(bank & 127) +*/ (value << 7);
1225                 return;
1226             }
1227 
1228             if (controller == 0x20) {
1229                 bank = (bank & (127 << 7)) + value;
1230                 return;
1231             }
1232 
1233             this.controller[controller] = value;
1234             if(controller < 0x20)
1235                 this.controller[controller + 0x20] = 0;
1236 
1237             for (int i = 0; i < voices.length; i++)
1238                 if (voices[i].active)
1239                     voices[i].controlChange(controller, value);
1240 
1241         }
1242     }
1243 
1244     public int getController(int controller) {
1245         synchronized (control_mutex) {
1246             // Should only return lower 7 bits,
1247             // even when controller is "boosted" higher.
1248             return this.controller[controller] & 127;
1249         }
1250     }
1251 
1252     public void tuningChange(int program) {
1253         tuningChange(0, program);
1254     }
1255 
1256     public void tuningChange(int bank, int program) {
1257         synchronized (control_mutex) {
1258             tuning = synthesizer.getTuning(new Patch(bank, program));
1259         }
1260     }
1261 
1262     public void programChange(int program) {
1263         programChange(bank, program);
1264     }
1265 
1266     public void programChange(int bank, int program) {
1267         bank = restrict14Bit(bank);
1268         program = restrict7Bit(program);
1269         synchronized (control_mutex) {
1270             mainmixer.activity();
1271             if(this.bank != bank || this.program != program)
1272             {
1273                 this.bank = bank;
1274                 this.program = program;
1275                 current_instrument = null;
1276             }
1277         }
1278     }
1279 
1280     public int getProgram() {
1281         synchronized (control_mutex) {
1282             return program;
1283         }
1284     }
1285 
1286     public void setPitchBend(int bend) {
1287         bend = restrict14Bit(bend);
1288         if (current_mixer != null)
1289             current_mixer.setPitchBend(bend);
1290         synchronized (control_mutex) {
1291             mainmixer.activity();
1292             co_midi_pitch[0] = bend * (1.0 / 16384.0);
1293             pitchbend = bend;
1294             for (int i = 0; i < voices.length; i++)
1295                 if (voices[i].active)
1296                     voices[i].setPitchBend(bend);
1297         }
1298     }
1299 
1300     public int getPitchBend() {
1301         synchronized (control_mutex) {
1302             return pitchbend;
1303         }
1304     }
1305 
1306     public void nrpnChange(int controller, int value) {
1307 
1308         /*
1309         System.out.println("(" + channel + ").nrpnChange("
1310                 + Integer.toHexString(controller >> 7)
1311                 + " " + Integer.toHexString(controller & 127)
1312                 + ", " + Integer.toHexString(value >> 7)
1313                 + " " + Integer.toHexString(value & 127) + ")");
1314          */
1315 
1316         if (synthesizer.getGeneralMidiMode() == 0) {
1317             if (controller == (0x01 << 7) + (0x08)) // Vibrato Rate
1318                 controlChange(76, value >> 7);
1319             if (controller == (0x01 << 7) + (0x09)) // Vibrato Depth
1320                 controlChange(77, value >> 7);
1321             if (controller == (0x01 << 7) + (0x0A)) // Vibrato Delay
1322                 controlChange(78, value >> 7);
1323             if (controller == (0x01 << 7) + (0x20)) // Brightness
1324                 controlChange(74, value >> 7);
1325             if (controller == (0x01 << 7) + (0x21)) // Filter Resonance
1326                 controlChange(71, value >> 7);
1327             if (controller == (0x01 << 7) + (0x63)) // Attack Time
1328                 controlChange(73, value >> 7);
1329             if (controller == (0x01 << 7) + (0x64)) // Decay Time
1330                 controlChange(75, value >> 7);
1331             if (controller == (0x01 << 7) + (0x66)) // Release Time
1332                 controlChange(72, value >> 7);
1333 
1334             if (controller >> 7 == 0x18) // Pitch coarse
1335                 controlChangePerNote(controller % 128, 120, value >> 7);
1336             if (controller >> 7 == 0x1A) // Volume
1337                 controlChangePerNote(controller % 128, 7, value >> 7);
1338             if (controller >> 7 == 0x1C) // Panpot
1339                 controlChangePerNote(controller % 128, 10, value >> 7);
1340             if (controller >> 7 == 0x1D) // Reverb
1341                 controlChangePerNote(controller % 128, 91, value >> 7);
1342             if (controller >> 7 == 0x1E) // Chorus
1343                 controlChangePerNote(controller % 128, 93, value >> 7);
1344         }
1345 
1346         int[] val_i = co_midi_nrpn_nrpn_i.get(controller);
1347         double[] val_d = co_midi_nrpn_nrpn.get(controller);
1348         if (val_i == null) {
1349             val_i = new int[1];
1350             co_midi_nrpn_nrpn_i.put(controller, val_i);
1351         }
1352         if (val_d == null) {
1353             val_d = new double[1];
1354             co_midi_nrpn_nrpn.put(controller, val_d);
1355         }
1356         val_i[0] = value;
1357         val_d[0] = val_i[0] * (1.0 / 16384.0);
1358 
1359         for (int i = 0; i < voices.length; i++)
1360             if (voices[i].active)
1361                 voices[i].nrpnChange(controller, val_i[0]);
1362 
1363     }
1364 
1365     public void rpnChange(int controller, int value) {
1366 
1367         /*
1368         System.out.println("(" + channel + ").rpnChange("
1369                 + Integer.toHexString(controller >> 7)
1370                 + " " + Integer.toHexString(controller & 127)
1371                 + ", " + Integer.toHexString(value >> 7)
1372                 + " " + Integer.toHexString(value & 127) + ")");
1373          */
1374 
1375         if (controller == 3) {
1376             tuning_program = (value >> 7) & 127;
1377             tuningChange(tuning_bank, tuning_program);
1378         }
1379         if (controller == 4) {
1380             tuning_bank = (value >> 7) & 127;
1381         }
1382 
1383         int[] val_i = co_midi_rpn_rpn_i.get(controller);
1384         double[] val_d = co_midi_rpn_rpn.get(controller);
1385         if (val_i == null) {
1386             val_i = new int[1];
1387             co_midi_rpn_rpn_i.put(controller, val_i);
1388         }
1389         if (val_d == null) {
1390             val_d = new double[1];
1391             co_midi_rpn_rpn.put(controller, val_d);
1392         }
1393         val_i[0] = value;
1394         val_d[0] = val_i[0] * (1.0 / 16384.0);
1395 
1396         for (int i = 0; i < voices.length; i++)
1397             if (voices[i].active)
1398                 voices[i].rpnChange(controller, val_i[0]);
1399     }
1400 
1401     public void resetAllControllers() {
1402         resetAllControllers(false);
1403     }
1404 
1405     public void resetAllControllers(boolean allControls) {
1406         synchronized (control_mutex) {
1407             mainmixer.activity();
1408 
1409             for (int i = 0; i < 128; i++) {
1410                 setPolyPressure(i, 0);
1411             }
1412             setChannelPressure(0);
1413             setPitchBend(8192);
1414             for (int i = 0; i < 128; i++) {
1415                 if (!dontResetControls[i])
1416                     controlChange(i, 0);
1417             }
1418 
1419             controlChange(71, 64); // Filter Resonance
1420             controlChange(72, 64); // Release Time
1421             controlChange(73, 64); // Attack Time
1422             controlChange(74, 64); // Brightness
1423             controlChange(75, 64); // Decay Time
1424             controlChange(76, 64); // Vibrato Rate
1425             controlChange(77, 64); // Vibrato Depth
1426             controlChange(78, 64); // Vibrato Delay
1427 
1428             controlChange(8, 64); // Balance
1429             controlChange(11, 127); // Expression
1430             controlChange(98, 127); // NRPN Null
1431             controlChange(99, 127); // NRPN Null
1432             controlChange(100, 127); // RPN = Null
1433             controlChange(101, 127); // RPN = Null
1434 
1435             // see DLS 2.1 (Power-on Default Values)
1436             if (allControls) {
1437 
1438                 keybasedcontroller_active = null;
1439                 keybasedcontroller_value = null;
1440 
1441                 controlChange(7, 100); // Volume
1442                 controlChange(10, 64); // Pan
1443                 controlChange(91, 40); // Reverb
1444 
1445                 for (int controller : co_midi_rpn_rpn.keySet()) {
1446                     // don't reset tuning settings
1447                     if (controller != 3 && controller != 4)
1448                         rpnChange(controller, 0);
1449                 }
1450                 for (int controller : co_midi_nrpn_nrpn.keySet())
1451                     nrpnChange(controller, 0);
1452                 rpnChange(0, 2 << 7);   // Bitch Bend sensitivity
1453                 rpnChange(1, 64 << 7);  // Channel fine tunning
1454                 rpnChange(2, 64 << 7);  // Channel Coarse Tuning
1455                 rpnChange(5, 64);       // Modulation Depth, +/- 50 cent
1456 
1457                 tuning_bank = 0;
1458                 tuning_program = 0;
1459                 tuning = new SoftTuning();
1460 
1461             }
1462 
1463         }
1464     }
1465 
1466     public void allNotesOff() {
1467         if (current_mixer != null)
1468             current_mixer.allNotesOff();
1469         synchronized (control_mutex) {
1470             for (int i = 0; i < voices.length; i++)
1471                 if (voices[i].on && voices[i].channel == channel
1472                         && voices[i].releaseTriggered == false) {
1473                     voices[i].noteOff(0);
1474                 }
1475         }
1476     }
1477 
1478     public void allSoundOff() {
1479         if (current_mixer != null)
1480             current_mixer.allSoundOff();
1481         synchronized (control_mutex) {
1482             for (int i = 0; i < voices.length; i++)
1483                 if (voices[i].on && voices[i].channel == channel)
1484                     voices[i].soundOff();
1485         }
1486     }
1487 
1488     public boolean localControl(boolean on) {
1489         return false;
1490     }
1491 
1492     public void setMono(boolean on) {
1493         if (current_mixer != null)
1494             current_mixer.setMono(on);
1495         synchronized (control_mutex) {
1496             allNotesOff();
1497             mono = on;
1498         }
1499     }
1500 
1501     public boolean getMono() {
1502         synchronized (control_mutex) {
1503             return mono;
1504         }
1505     }
1506 
1507     public void setOmni(boolean on) {
1508         if (current_mixer != null)
1509             current_mixer.setOmni(on);
1510         allNotesOff();
1511     // Omni is not supported by GM2
1512     }
1513 
1514     public boolean getOmni() {
1515         return false;
1516     }
1517 
1518     public void setMute(boolean mute) {
1519         if (current_mixer != null)
1520             current_mixer.setMute(mute);
1521         synchronized (control_mutex) {
1522             this.mute = mute;
1523             for (int i = 0; i < voices.length; i++)
1524                 if (voices[i].active && voices[i].channel == channel)
1525                     voices[i].setMute(mute);
1526         }
1527     }
1528 
1529     public boolean getMute() {
1530         synchronized (control_mutex) {
1531             return mute;
1532         }
1533     }
1534 
1535     public void setSolo(boolean soloState) {
1536         if (current_mixer != null)
1537             current_mixer.setSolo(soloState);
1538 
1539         synchronized (control_mutex) {
1540             this.solo = soloState;
1541 
1542             boolean soloinuse = false;
1543             for (SoftChannel c : synthesizer.channels) {
1544                 if (c.solo) {
1545                     soloinuse = true;
1546                     break;
1547                 }
1548             }
1549 
1550             if (!soloinuse) {
1551                 for (SoftChannel c : synthesizer.channels)
1552                     c.setSoloMute(false);
1553                 return;
1554             }
1555 
1556             for (SoftChannel c : synthesizer.channels)
1557                 c.setSoloMute(!c.solo);
1558 
1559         }
1560 
1561     }
1562 
1563     private void setSoloMute(boolean mute) {
1564         synchronized (control_mutex) {
1565             if (solomute == mute)
1566                 return;
1567             this.solomute = mute;
1568             for (int i = 0; i < voices.length; i++)
1569                 if (voices[i].active && voices[i].channel == channel)
1570                     voices[i].setSoloMute(solomute);
1571         }
1572     }
1573 
1574     public boolean getSolo() {
1575         synchronized (control_mutex) {
1576             return solo;
1577         }
1578     }
1579 }